import { Empty, Select, Spin } from 'antd';
import { SelectProps } from 'antd/es/select';
import debounce from 'lodash/debounce';
import React, { useEffect } from 'react';

interface DebounceSelectProps<ValueType = any>
  extends Omit<SelectProps<ValueType>, 'options' | 'children'> {
  /**远程请求列表数据 */
  fetchOptions: (searchWord?: string) => Promise<ValueType[]>;
  /**防抖时间 */
  debounceTimeout?: number;
}

/**
 * 远程搜索控件
 * 一个带有远程搜索，防抖控制，请求时序控制，加载状态的多选示例。
 * @export
 * @template ValueType
 * @param {DebounceSelectProps} { fetchOptions, debounceTimeout = 800, ...props }
 * @return {*}
 */
export function DebounceSelect<
  ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any
>({ fetchOptions, debounceTimeout = 800, ...props }: DebounceSelectProps) {
  const [fetching, setFetching] = React.useState(false);
  const [options, setOptions] = React.useState<ValueType[]>();
  const fetchRef = React.useRef(0);

  const debounceFetcher = React.useMemo(() => {
    const loadOptions = (value: string) => {
      console.log('DebounceSelect组件【搜索条件】:', value);
      fetchRef.current += 1;
      const fetchId = fetchRef.current;
      setFetching(true);
      fetchOptions(value).then(newOptions => {
        if (fetchId !== fetchRef.current) {
          // for fetch callback order
          console.log('选项列表不变', fetchId);
          return;
        }
        setOptions(newOptions);
        setFetching(false);
      });
    };

    return debounce(loadOptions, debounceTimeout);
  }, [fetchOptions, debounceTimeout]);

  useEffect(() => {
    console.log('DebounceSelect组件【加载】初始化列表数据***');
    debounceFetcher('');
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <Select<ValueType>
      filterOption={false}
      onFocus={() => {
        debounceFetcher('');
      }}
      onSearch={debounceFetcher}
      notFoundContent={
        fetching ? <Spin size="small" /> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
      }
      {...props}
      options={options}
    />
  );
}
